import { ExportService } from '@/services/export'
import { FormatProcessorFactory, HtmlProcessor, PdfProcessor, MarkdownProcessor } from './format-processors'
import { 
  ExportType, 
  ExportFormat, 
  ExportSession, 
  ExportProgress,
  DocData,
  MergeOption
} from './export-types'
import { Document, Packer, Paragraph, TextRun } from 'docx'

// 导出管理器类
export class ExportManager {
  private static instance: ExportManager
  private activeSessions = new Map<string, ExportSession>()
  private maxConcurrentTasks = 10
  private runningTasks = 0
  private isExporting = false

  private constructor() {}

  static getInstance(): ExportManager {
    if (!ExportManager.instance) {
      ExportManager.instance = new ExportManager()
    }
    return ExportManager.instance
  }

  // 创建导出会话
  createSession(
    exportType: ExportType,
    format: ExportFormat,
    options: {
      teamId?: string
      projectId?: string
      directoryId?: string
      docId?: string
      mergeOption?: MergeOption
      addWatermark?: boolean
    }
  ): ExportSession {
    console.log('ExportManager createSession 被调用:', { exportType, format, options })
    
    const sessionId = `export_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
    
    const session: ExportSession = {
      sessionId,
      exportType,
      format,
      mergeOption: options.mergeOption || MergeOption.SEPARATE,
      addWatermark: options.addWatermark || false,
      totalDocs: 0,
      completedDocs: [],
      failedDocs: [],
      currentProgress: 0,
      startTime: new Date(),
      lastUpdateTime: new Date(),
      status: 'running',
      teamId: options.teamId,
      projectId: options.projectId,
      directoryId: options.directoryId,
      docId: options.docId
    }

    console.log('创建的会话对象:', session)

    this.activeSessions.set(session.sessionId, session)
    return session
  }

  // 执行导出任务
  async executeExport(
    session: ExportSession,
    projectName: string,
    directoryName?: string,
    onProgress?: (progress: ExportProgress) => void,
    isDark: boolean = false,
    font: string = ''
  ): Promise<void> {
    if (this.runningTasks >= this.maxConcurrentTasks) {
      throw new Error('导出任务数量已达上限，请稍后重试')
    }

    this.runningTasks++
    
    try {
      // 更新会话状态
      session.status = 'running'
      session.lastUpdateTime = new Date()
      this.updateSession(session)

      // 获取文档数据
      const docs = await this.getDocuments(session)
      session.totalDocs = docs.length
      this.updateSession(session)

      if (docs.length === 0) {
        throw new Error('没有找到可导出的文档')
      }

      // 检查文件大小
      const totalSize = docs.reduce((size, doc) => {
        return size + (doc.docContent?.length || 0)
      }, 0)

      if (!ExportService.checkFileSize('a'.repeat(totalSize))) {
        throw new Error('文档总大小超过50MB限制')
      }

      // 处理文档格式
      let content: string | Blob | Promise<Blob>
      let filename = ''
      let mimeType = ''

      // 多文档导出（目录或项目）或单文档多选
      const isMultiDoc = session.exportType === ExportType.DIRECTORY || 
                        session.exportType === ExportType.CURRENT_DIRECTORY || 
                        session.exportType === ExportType.PROJECT ||
                        (session.exportType === ExportType.SINGLE && session.docId && session.docId.includes(','))

      if (isMultiDoc && session.mergeOption === MergeOption.MERGE) {
        // 合并为单个文件
        if (session.format === ExportFormat.PDF) {
          // PDF导出
          const processor = new PdfProcessor()
          content = await processor.process(docs, session.addWatermark, isDark, font)
          filename = ExportService.generateFileName(
            session.exportType,
            session.format,
            projectName,
            directoryName,
            undefined,
            true // isMerged
          )
          mimeType = 'application/pdf'
        } else if (session.format === ExportFormat.HTML) {
          // HTML导出
          const processor = new HtmlProcessor()
          content = processor.process(docs, session.addWatermark, isDark, font)
          filename = ExportService.generateFileName(
            session.exportType,
            session.format,
            projectName,
            directoryName,
            undefined,
            true // isMerged
          )
          mimeType = 'text/html'
        } else {
          // Markdown导出
          const processor = new MarkdownProcessor()
          content = processor.process(docs, session.addWatermark)
          filename = ExportService.generateFileName(
            session.exportType,
            session.format,
            projectName,
            directoryName,
            undefined,
            true // isMerged
          )
          mimeType = 'text/markdown'
        }

        // 下载合并文件
        if (content instanceof Blob) {
          console.log('下载合并Blob文件:', filename, '格式:', session.format, 'MIME类型:', mimeType)
          
          const extension = ExportService.getFileExtension(session.format)
          if (!filename.endsWith(`.${extension}`)) {
            filename = `${filename}.${extension}`
            console.log('修正后的文件名:', filename)
          }
          
          const url = URL.createObjectURL(content)
          const link = document.createElement('a')
          link.href = url
          link.download = filename
          link.style.display = 'none'
          document.body.appendChild(link)
          link.click()
          document.body.removeChild(link)
          URL.revokeObjectURL(url)
          console.log('合并Blob文件下载完成:', filename)
        } else if (typeof content === 'string') {
          ExportService.downloadFile(content, filename, mimeType)
          console.log('下载合并字符串文件:', filename, '格式:', session.format, 'MIME类型:', mimeType)
        }

      } else if (isMultiDoc && session.mergeOption === MergeOption.SEPARATE) {
        // 分别导出文件，打包为ZIP
        if (session.exportType === ExportType.SINGLE && session.docId && session.docId.includes(',')) {
          // 单文档多选，使用项目名作为ZIP文件名
          await this.exportDirectoryAsZip(session, docs, projectName, '多选文档', onProgress, isDark, font)
        } else {
          // 目录或项目导出
          await this.exportDirectoryAsZip(session, docs, projectName, directoryName, onProgress, isDark, font)
        }
        return
      } else {
        // 单文档导出
        if (session.format === ExportFormat.PDF) {
          // PDF导出
          const processor = new PdfProcessor()
          content = await processor.process(docs, session.addWatermark, isDark, font)
          filename = ExportService.generateFileName(
            session.exportType,
            session.format,
            projectName,
            directoryName,
            docs[0]?.docTitle
          )
          mimeType = 'application/pdf'
        } else if (session.format === ExportFormat.HTML) {
          // HTML导出
          const processor = new HtmlProcessor()
          content = processor.process(docs, session.addWatermark, isDark, font)
          filename = ExportService.generateFileName(
            session.exportType,
            session.format,
            projectName,
            directoryName,
            docs[0]?.docTitle
          )
          mimeType = 'text/html'
        } else {
          // Markdown导出
          const processor = new MarkdownProcessor()
          content = processor.process(docs, session.addWatermark)
          filename = ExportService.generateFileName(
            session.exportType,
            session.format,
            projectName,
            directoryName,
            docs[0]?.docTitle
          )
          mimeType = 'text/markdown'
        }

        // 下载文件
        if (content instanceof Blob) {
          console.log('下载Blob文件:', filename, '格式:', session.format, 'MIME类型:', mimeType)
          
          // 确保文件名包含正确的扩展名
          const extension = ExportService.getFileExtension(session.format)
          if (!filename.endsWith(`.${extension}`)) {
            filename = `${filename}.${extension}`
            console.log('修正后的文件名:', filename)
          }
          
          const url = URL.createObjectURL(content)
          const link = document.createElement('a')
          link.href = url
          link.download = filename
          link.style.display = 'none'
          document.body.appendChild(link)
          link.click()
          document.body.removeChild(link)
          URL.revokeObjectURL(url)
          console.log('Blob文件下载完成:', filename)
        } else if (typeof content === 'string') {
          ExportService.downloadFile(content, filename, mimeType)
          console.log('下载字符串文件:', filename, '格式:', session.format, 'MIME类型:', mimeType)
        }
      }

      // 更新完成状态
      session.status = 'completed'
      session.completedDocs = docs.map(doc => doc.docTitle)
      session.currentProgress = 100
      session.lastUpdateTime = new Date()
      this.updateSession(session)

      // 通知进度更新
      if (onProgress) {
        onProgress({
          total: docs.length,
          current: docs.length,
          status: 'completed',
          message: '导出完成'
        })
      }

    } catch (error) {
      // 更新失败状态
      session.status = 'failed'
      session.lastUpdateTime = new Date()
      this.updateSession(session)

      // 通知进度更新
      if (onProgress) {
        onProgress({
          total: session.totalDocs,
          current: 0,
          status: 'error',
          message: error instanceof Error ? error.message : '导出失败'
        })
      }

      throw error
    } finally {
      this.runningTasks--
    }
  }

  // 目录导出为ZIP文件
  private async exportDirectoryAsZip(
    session: ExportSession,
    docs: DocData[],
    projectName: string,
    directoryName?: string,
    onProgress?: (progress: ExportProgress) => void,
    isDark: boolean = false,
    font: string = ''
  ): Promise<void> {
    // 动态导入 JSZip
    const JSZip = (await import('jszip')).default
    const zip = new JSZip()
    const extension = ExportService.getFileExtension(session.format)
    
    // 通知进度更新
    if (onProgress) {
      onProgress({
        total: docs.length,
        current: 0,
        status: 'processing',
        message: '正在处理文档...'
      })
    }

    // 处理每个文档
    for (let i = 0; i < docs.length; i++) {
      const doc = docs[i]
      
      try {
        let content: string | Blob
        let filename = `${doc.docTitle}.${extension}`

        // 根据格式处理文档
        if (session.format === ExportFormat.PDF) {
          const processor = new PdfProcessor()
          content = await processor.process([doc], session.addWatermark, isDark, font)
        } else if (session.format === ExportFormat.HTML) {
          const processor = new HtmlProcessor()
          content = processor.process([doc], session.addWatermark, isDark, font)
        } else {
          // Markdown格式
          const processor = new MarkdownProcessor()
          content = processor.process([doc], session.addWatermark)
        }

        // 添加到ZIP
        if (content instanceof Blob) {
          const arrayBuffer = await content.arrayBuffer()
          zip.file(filename, arrayBuffer)
        } else {
          zip.file(filename, content)
        }

        // 更新进度
        session.completedDocs.push(doc.docTitle)
        session.currentProgress = Math.round(((i + 1) / docs.length) * 100)
        this.updateSession(session)

        if (onProgress) {
          onProgress({
            total: docs.length,
            current: i + 1,
            status: 'processing',
            message: `正在处理: ${doc.docTitle}`,
            currentDoc: doc.docTitle
          })
        }

      } catch (error) {
        session.failedDocs.push(doc.docTitle)
        console.error(`处理文档 ${doc.docTitle} 失败:`, error)
      }
    }

    // 生成ZIP文件
    if (onProgress) {
      onProgress({
        total: docs.length,
        current: docs.length,
        status: 'downloading',
        message: '正在生成ZIP文件...'
      })
    }

    const zipBlob = await zip.generateAsync({ type: 'blob' })
    const zipFilename = `${projectName}-${directoryName || '目录'}.zip`

    // 下载ZIP文件
    const url = URL.createObjectURL(zipBlob)
    const link = document.createElement('a')
    link.href = url
    link.download = zipFilename
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    URL.revokeObjectURL(url)

    // 更新完成状态
    session.status = 'completed'
    session.currentProgress = 100
    session.lastUpdateTime = new Date()
    this.updateSession(session)

    if (onProgress) {
      onProgress({
        total: docs.length,
        current: docs.length,
        status: 'completed',
        message: 'ZIP文件导出完成'
      })
    }
  }

  // 获取文档数据
  private async getDocuments(session: ExportSession): Promise<DocData[]> {
    const { teamId, projectId, directoryId, docId, exportType } = session

    if (!teamId || !projectId) {
      throw new Error('缺少必要的参数')
    }

    switch (exportType) {
      case ExportType.SINGLE:
        if (!docId) {
          throw new Error('单文档导出需要文档ID')
        }
        
        // 检查是否包含多个文档ID（用逗号分隔）
        if (docId.includes(',')) {
          const docIds = docId.split(',').map(id => id.trim()).filter(id => id)
          const docs: DocData[] = []
          
          for (const id of docIds) {
            try {
              const doc = await ExportService.getDocById(id)
              docs.push(doc)
            } catch (error) {
              console.error(`获取文档 ${id} 失败:`, error)
              // 继续处理其他文档
            }
          }
          
          if (docs.length === 0) {
            throw new Error('没有成功获取到任何文档')
          }
          
          return docs
        } else {
          // 单个文档
          const doc = await ExportService.getDocById(docId)
          return [doc]
        }

      case ExportType.DIRECTORY:
        if (!directoryId) {
          throw new Error('目录导出需要目录ID')
        }
        return await ExportService.getDirectoryDocs(teamId, projectId, directoryId)

      case ExportType.CURRENT_DIRECTORY:
        if (!directoryId) {
          throw new Error('当前目录导出需要目录ID')
        }
        return await ExportService.getCurrentDirectoryDocs(teamId, projectId, directoryId)

      case ExportType.PROJECT:
        return await ExportService.getProjectDocs(teamId, projectId)

      default:
        throw new Error('不支持的导出类型')
    }
  }

  // 暂停导出任务
  pauseSession(sessionId: string): void {
    const session = this.activeSessions.get(sessionId)
    if (session && session.status === 'running') {
      session.status = 'paused'
      session.lastUpdateTime = new Date()
      this.updateSession(session)
    }
  }

  // 恢复导出任务
  resumeSession(sessionId: string): void {
    const session = this.activeSessions.get(sessionId)
    if (session && session.status === 'paused') {
      session.status = 'running'
      session.lastUpdateTime = new Date()
      this.updateSession(session)
    }
  }

  // 取消导出任务
  cancelSession(sessionId: string): void {
    const session = this.activeSessions.get(sessionId)
    if (session) {
      session.status = 'failed'
      session.lastUpdateTime = new Date()
      this.updateSession(session)
    }
  }

  // 获取会话信息
  getSession(sessionId: string): ExportSession | undefined {
    return this.activeSessions.get(sessionId)
  }

  // 获取所有活跃会话
  getAllSessions(): ExportSession[] {
    return Array.from(this.activeSessions.values())
  }

  // 清理完成的会话
  cleanupCompletedSessions(): void {
    const now = new Date()
    const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000)

    for (const [sessionId, session] of this.activeSessions.entries()) {
      if (
        (session.status === 'completed' || session.status === 'failed') &&
        session.lastUpdateTime < oneHourAgo
      ) {
        this.activeSessions.delete(sessionId)
      }
    }
  }

  // 获取运行中的任务数量
  getRunningTaskCount(): number {
    return this.runningTasks
  }

  // 获取可用任务数量
  getAvailableTaskCount(): number {
    return this.maxConcurrentTasks - this.runningTasks
  }

  // 更新会话
  private updateSession(session: ExportSession): void {
    this.activeSessions.set(session.sessionId, session)
  }

  async exportContent(
    format: ExportFormat,
    content: string,
    filename: string,
    options?: {
      docId?: string;
      directoryId?: string;
      directoryName?: string;
    }
  ): Promise<void> {
    if (this.isExporting) {
      throw new Error('导出正在进行中，请稍后再试');
    }

    this.isExporting = true;

    try {
      switch (format) {
        case ExportFormat.MARKDOWN:
          await this.exportMarkdown(content, filename);
          break;
        case ExportFormat.HTML:
          await this.exportHTML(content, filename);
          break;
        case ExportFormat.PDF:
          await this.exportPDF(content, filename);
          break;
        default:
          throw new Error('不支持的导出格式');
      }
    } finally {
      this.isExporting = false;
    }
  }

  private async exportMarkdown(content: string, filename: string): Promise<void> {
    const blob = new Blob([content], { type: 'text/markdown' });
    this.downloadFile(blob, `${filename}.md`);
  }

  private async exportHTML(content: string, filename: string): Promise<void> {
    // 使用新的HtmlProcessor来获得留白效果
    const processor = new HtmlProcessor()
    const htmlContent = processor.process([{ docTitle: filename, docContent: content, createTime: new Date().toISOString() }], false, false, '')
    const blob = new Blob([htmlContent], { type: 'text/html' });
    this.downloadFile(blob, `${filename}.html`);
  }

  private async exportPDF(content: string, filename: string): Promise<void> {
    const { default: html2pdf } = await import('html2pdf.js');
    
    const element = document.createElement('div');
    element.innerHTML = content;
    element.style.padding = '20px';
    element.style.fontFamily = 'Arial, sans-serif';
    element.style.fontSize = '14px';
    element.style.lineHeight = '1.6';
    
    const opt = {
      margin: 1,
      filename: `${filename}.pdf`,
      image: { type: 'jpeg', quality: 0.98 },
      html2canvas: { scale: 2 },
      jsPDF: { unit: 'in', format: 'a4', orientation: 'portrait' }
    };

    await html2pdf().set(opt).from(element).save();
  }

  private downloadFile(blob: Blob, filename: string): void {
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = filename;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(url);
  }

  isCurrentlyExporting(): boolean {
    return this.isExporting;
  }
}

// 将 Postman v2.1 collection 转为 markdown 文本
export function postmanToMarkdown(postmanJson: any): string {
  let md = '';
  function parseItem(item: any) {
    if (item.item) {
      item.item.forEach(parseItem);
      return;
    }
    const req = item.request;
    md += `##### 简要描述\n\n- ${item.name}\n\n`;
    md += `##### 请求URL\n - \`${req.url?.raw || ''}\` \n\n`;
    md += `##### 请求方式\n\n- ${req.method?.toLowerCase() || ''}\n\n`;
    // 请求头表格
    md += `##### 请求头\n\n| Key | Value | 类型 |\n|:-----: |:-----: |:-----:|\n`;
    if (Array.isArray(req.header) && req.header.length > 0) {
      req.header.forEach((h: any) => {
        md += `| ${h.key} |${h.value}|${h.type}|\n`;
      });
    }
    // 无请求头时只保留表头，不多余输出
    md += `\n`;
    md += `##### 请求参数类型\n\n- ${req.body?.mode || '无'}\n\n`;
    // raw 参数处理
    if (req.body?.mode === 'raw') {
      let rawStr = req.body.raw || '';
      let pretty = rawStr;
      try {
        const obj = JSON.parse(rawStr);
        pretty = JSON.stringify(obj, null, 2);
      } catch (e) {
        // 不是合法 JSON，原样输出
      }
      md += `##### 请求参数示例  \n\`\`\`json\n${pretty}\n\`\`\`\n \n`;
    }
    md += `##### 成功返回示例  \n\`\`\`\n[]\n\n\`\`\` \n\n`;
  }
  (postmanJson.item || []).forEach(parseItem);
  return md;
} 